package com.duanjw.springframework.aop.config;

import com.duanjw.springframework.aop.dao.UserDao;
import com.duanjw.springframework.aop.dao.impl.UserDaoImpl;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.*;
import org.springframework.stereotype.Component;

/**
 * 日志切面，默认是单例
 * ---
 * jdk代理 基于接口，因为java是单继承。jdk动态代理会继承Proxy对象。
 * CGLIB 基于继承。this。 target是父子类
 * <p>
 * ----
 * target 目标对象，我们自己写的对象
 * this 是代理对象，框架基于目标对象帮我们生产的对象
 *
 * @author duanjw
 */
@Component
@Aspect
public class LogAspectj {

    /**
     * 切点
     */
    @Pointcut("execution(* com.duanjw.springframework.aop.dao..*.*(..))")
    public void pointCut() {
    }

    /**
     * 方法执行前通知
     */
    @Before("pointCut()")
    public void before(JoinPoint joinpoint) {
        System.out.println("-----before-----，this:" + joinpoint.getThis() + "，target：" + joinpoint.getTarget());
    }

    /**
     * 方法执行完通知
     */
    @After("pointCut()")
    public void after(JoinPoint joinpoint) {
        System.out.println("-----after-----，this:" + joinpoint.getThis() + "，target：" + joinpoint.getTarget());
    }

    /**
     * 环绕通知
     * ProceedingJoinPoint：当前正在执行的连接点（方法）
     */
    @Around("pointCut()")
    public void around(ProceedingJoinPoint pjp) throws Throwable {
        System.out.println("-----around-----");

        // 如果有参数，我们把所有参数加一个`update`字符串
        Object[] args = pjp.getArgs();
        if (args != null) {
            for (int i = 0; i < args.length; i++) {
                args[i] += " update";
            }
            pjp.proceed(args);
        } else {
            pjp.proceed();
        }
    }


    /**
     * TestUserDaoImpl没有实现UserDao，通过Aspect实现UserDao
     * defaultImpl
     */
    @DeclareParents(value = "com.duanjw.springframework.aop.dao..*", defaultImpl = UserDaoImpl.class)
    public static UserDao userDao;


}
